local MJCONST = require "const"
local PAICONST = MJCONST.PAICONST
local ACTIONTYPE={WIK_HU=1, WIK_PENG=2, WIK_ANGANG=3, WIK_JIAGANG=4, WIK_JIEGANG=5}
local HUTYPE = {HT_NULL=0, HT_PINGHU=1, HT_PENGPENGHU=0x2}
local FAN = {}

function DeepCopy( obj )	
	local InTable = {};
	local function Func(obj)
		if type(obj) ~= "table" then   --判断表中是否有表
			return obj;
		end
		local NewTable = {};  --定义一个新表
		InTable[obj] = NewTable;  --若表中有表，则先把表给InTable，再用NewTable去接收内嵌的表
		for k,v in pairs(obj) do  --把旧表的key和Value赋给新表
			NewTable[Func(k)] = Func(v);
		end
		return setmetatable(NewTable, getmetatable(obj))--赋值元表
	end
	return Func(obj) --若表中有表，则把内嵌的表也复制了
end

function table.merge( tDest, tSrc , bFilterSame, filed)
	if not tSrc or not tDest then return end
	local i = 1
    for k, v in pairs( tSrc ) do
		local bFind = false
		if bFilterSame then     --剔重
			if not filed then
				for j = 1, #tDest do if tDest[j] == v then bFind = true end end
			else
				for j = 1, #tDest do if tDest[j][filed] == v[filed] then bFind = true end end
			end
		end
        if not bFind or not bFilterSame then tDest[#tDest + i] = v end
    end
end

function MergeTable( tA, tB , bFilterSame)
	if not tB and not tA then return {} end
    tA = tA or {}
    tB = tB or {}
    local M = DeepCopy(tA)
	local i = 1
    for k, v in pairs( tB ) do
      local bFind = false
      if bFilterSame then     --剔重
        for j = 1, #tA do if tA[j] == v then bFind = true end end
      end
      if not bFind or not bFilterSame then M[#M + i] = v end
    end
    return M
end


local table_mjCardData =
{
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						--万
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						--条
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						--同
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x31,0x32,0x33,				--千字，红花，白花				
	0x31,0x32,0x33,							
	0x31,0x32,0x33,							
	0x31,0x32,0x33,						   
    0x41,0x42,0x43,0x44,0x45    --百搭
};


MjLogic = {table_RepertoryCard = {}}

function MjLogic:New (obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self
	return obj
end

function MjLogic:Init(total_num)
    local num = total_num
    if not total_num then num = PAICONST.PAI_TOTAL end 
	for i = 1, num do 
		self.table_RepertoryCard[i] = table_mjCardData[i]
	end
end

local function randCardLocal(card)
	local tab_RandCard = {}
	local len = #card
	math.randomseed(tostring(os.time()):reverse():sub(1, 7))
	for i = 1, len do
		local r = math.random(1, len - i + 1)
		tab_RandCard[i], card[r] = card[r], card[len - i + 1]
	end
	return tab_RandCard
end


function MjLogic:PaiArrToIndexArr(paiArr)
	local indexArr = {}
	for i = 1, PAICONST.MAX_INDEX do indexArr[i] = 0 end	
	for i = 1, #paiArr do
		local index = MjLogic:ValToIndex(paiArr[i])
		indexArr[index] = indexArr[index] + 1  
	end
	return indexArr
end

function MjLogic:randCard(count)
	for i = 1, count do
		self.table_RepertoryCard = randCardLocal(self.table_RepertoryCard)
	end
end

function MjLogic:IndexToVal(index)
    if index >= 31 then 
        return 0x40 + index % 10
    else
        local ind = index - 1
        local s, _ = ind//9
        return (s<<4)|(ind%9+1);
    end
end

function MjLogic:ValToIndex(val)
    if val > 0x40 then 
        return 30 + val - 0x40    --百搭为[41，42，43，44，45]
    else 
        return ((val&PAICONST.MASK_COLOR)>>4)*9+(val&PAICONST.MASK_VALUE)
    end
end

function MjLogic:GetHandCardNum(arrIndex)
	local num = 0
	for i = 1, #arrIndex do 
		num = num + arrIndex[i]
	end
	return num
end

function TabKsqAdd(t1, t2)
    t1, t2 = (t1 or {}), (t2 or {})
    local t = {}
    t.k = (t1.k or 0) + (t2.k or 0)
    t.s = (t1.s or 0) + (t2.s or 0)
    t.kv = MergeTable(t1.kv, t2.kv, true)
    t.sv = MergeTable(t1.sv, t2.sv, true)
    
    t.j = (t1.j or 0) + (t2.j or 0)  --将
    if t.j == 1 then
        t.jv = MergeTable(t1.jv, t2.jv, true)
    end

    return t
end

function MjLogic:ProcessSerialPai(tabPai, tabKsq)    --从一段连续的牌中计算听什么牌
	if #tabPai % 3 == 0 then 
		local ret = false 
        local bOk, ksq = self:ValidPai(tabPai)
		if bOk then
            ret = 1
            if tabKsq then tabKsq.ksq = TabKsqAdd(tabKsq.ksq, ksq) end
        end 
		return ret, {}    --3的倍数直接判断
	end
	local tingData = self:CalHuCommonPai(tabPai)   
	local bOk, ksq = self:ValidPai(tabPai)
    if tabKsq then tabKsq.ksq = TabKsqAdd(tabKsq.ksq, ksq) end
	if bOk == nil then  --1,4,7,10,13,
		if #tingData == 0 then return false 
		else return 0, tingData end
	else
		if #tingData == 0 and not bOk then return false  --2,5,8 
		else  
			local ret = 0
			if bOk then ret = 1 end
		    return ret, tingData 
		end
	end
	return 0, tingData         --1表示不缺,0表示缺一个字才成一句  22，333好像返回的也是不缺
end

function MjLogic:ValidPai(tabPai, param2)
	if #tabPai == 0 then return true end
	local func = {nil, 
				self.Valid2Pai, 
				self.Valid3Pai,
				nil;
				self.Valid5Pai,
				self.Valid6Pai,
				nil,
				self.Valid8Pai,
				self.Valid9Pai,
				nil,
				self.Valid11Pai,
				self.Valid12Pai,
				nil,
				self.Valid14Pai}
	if func[#tabPai] == nil then return nil end
	local sum = 0
	for i = 1, #tabPai do
		sum = sum + tabPai[i]
	end
	tabPai.d = sum
	return func[#tabPai](self, tabPai)
end

function MjLogic:SplitPai(tabPai, split)   --按顺序拆分
    local tabExtra = {}
	for k = 1, #split do 
		local card1 = {}
		local card2 = {}
		for i = 1, split[k] do
			table.insert(card1, tabPai[i])
		end
		for i = 1, #tabPai - split[k] do 
			table.insert(card2, tabPai[i + split[k]])
		end
		local bOk1, tabE1 = self:ValidPai(card1)
        local bOk2, tabE2 = self:ValidPai(card2)
		if bOk1 and bOk2 then
            tabExtra = TabKsqAdd(tabE1, tabE2)
            return true, tabExtra
        end
	end
	return false
end

function MjLogic:SelectSerial3(tabPai, bRev)   --选择连续的不重叠的3个
	local paiSeries1 = {}
	local paiSeries2 = {}
	local b, e, s = 1, #tabPai, 1    --begin,end, step
	if bRev then b, e, s = #tabPai, 1, -1 end
	for i = b, e, s do
		if tabPai[i] ~= paiSeries1[#paiSeries1] and #paiSeries1 < 3 then
			table.insert(paiSeries1, tabPai[i])
		else table.insert(paiSeries2, tabPai[i])
		end
	end
	return paiSeries1, paiSeries2
end

function MjLogic:ValidCommonPai(tabPai, split)  
	local bOk, tabKsq = false, {}
	bOk, tabKsq  = self:SplitPai(tabPai, split)   --按顺序拆分
	if bOk then return true, tabKsq end
	local paiSeries1, paiSeries2 = self:SelectSerial3(tabPai)       --先正选三个顺子
    local bOk1, tabE1 = self:ValidPai(paiSeries1)
    local bOk2, tabE2 = self:ValidPai(paiSeries2)
	if bOk1 and bOk2 then
        tabExtra = TabKsqAdd(tabE1, tabE2)
        return true, tabExtra
    end
	paiSeries1, paiSeries2 = self:SelectSerial3(tabPai, true)       --反选三个顺子
	bOk1, tabE1 = self:ValidPai(paiSeries1)
    bOk2, tabE2 = self:ValidPai(paiSeries2)
	if bOk1 and bOk2 then
        tabExtra = TabKsqAdd(tabE1, tabE2)
        return true, tabExtra
    end
	return false
end

function MjLogic:Valid2Pai(tabPai)   --判断是不是将
    local tabKsq = {j = 0, jv = {0}}
    local dui = (tabPai[1] == tabPai[2])
    if dui then 
        tabKsq.j = 1
        tabKsq.jv = {tabPai[1]} 
    end
	return dui, tabKsq
end

function MjLogic:Valid3Pai(tabPai)   --判断是不是连续的3个数  例如222,234
    local tabKsq = {kv = {}, sv = {}}
	if #tabPai ~= 3 then return false end
	local sum = 0
	for i = 1, #tabPai do 
		sum = sum + tabPai[i]
	end	
	if sum % 3 ~= 0 then return false end
	local av = sum / 3
	if (tabPai[2] ~= av) then return false end
	if tabPai[1] == tabPai[2] and tabPai[2] == tabPai[3] then   --刻子
        if tabKsq then
            tabKsq.k = tabKsq.k or 0 + 1
            tabKsq.kv = {av}
        end
        return true, tabKsq
    end    
	local bOk = true
	if (tabPai[1] ~= av) then bOk = (bOk and (math.abs((av- tabPai[1]))) == 1) end
	if (tabPai[3] ~= av) then bOk = (bOk and (math.abs((av- tabPai[3]))) == 1) end
    if bOk and tabKsq then
        tabKsq.s = tabKsq.s or 0 + 1 
        tabKsq.sv = {av}
    end
	return bOk, tabKsq  --
end

function MjLogic:Valid5Pai(tabPai)
    local tabExtra
	local bOk = false
	local split = {2, 3}
	bOk, tabExtra = self:SplitPai(tabPai, split)
	if bOk then return true, tabExtra end
	local paiSeries1, paiSeries2 = self:SelectSerial3(tabPai)  --计算重叠的23334(即234,33)
    local bOk1, tabE1 = self:ValidPai(paiSeries1)
    local bOk2, tabE2 = self:ValidPai(paiSeries2)
	if bOk1 and bOk2 then
        tabExtra = TabKsqAdd(tabE1, tabE2)
        return true, tabExtra
    end
    
	return false
end

function MjLogic:Valid6Pai(tabPai)
	local split = {3}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid8Pai(tabPai)
	local split = {3, 5}
	return self:ValidCommonPai(tabPai, split)
end 

function MjLogic:Valid9Pai(tabPai)
	local split = {3, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid11Pai(tabPai)
	local split = {5, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid12Pai(tabPai)
	local split = {6, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid14Pai(tabPai)
	local split = {6, 8}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:CalHuCommonPai(tabPai)   --牌已经是连续的
    table.sort(tabPai)
	if #tabPai % 3 == 0 then return {} end
	local min = tabPai[1] - 1
	local max = tabPai[#tabPai] + 1
	if tabPai[1] % 16 == 1 then min = tabPai[1] end
	if tabPai[#tabPai] % 16 == 9 then max = tabPai[#tabPai] end
	local huPai = {}
	local v = min
	repeat
		local tab = DeepCopy(tabPai)
		table.insert(tab, v)
		table.sort(tab)
		if self:ValidPai(tab) then 
            table.insert(huPai, v)
        end
		v = v + 1
	until v >  max
	return huPai
end

function MjLogic:ValidShouPai(tabWan, tabTiao, tabTong, tabZi)   --听,胡牌时(即13或14张牌)都通用
	local nZi1, nZi2 = 0, 0
	local nZi = 0    --共有多少字牌
	for i = 1, #tabZi do
		if tabZi[i] % 3 == 1 then nZi1 = nZi1 + 1 end
		if tabZi[i] % 3 == 2 then nZi2 = nZi2 + 1 end
		if tabZi[i] > 0 then nZi = nZi + tabZi[i] end
	end
	local nTotal = tabWan.n + tabTiao.n + tabTong.n + nZi
	local nDanTotal = 1
	local nDuiTotal = 2
	if nTotal % 3 == 2 then nDanTotal = 0 nDuiTotal = 1 end
	if nZi1 > nDanTotal then return false end       --单个字超过1个
	if nZi2 > nDuiTotal then return false end       --对子字超过2个
	if nZi1 * nZi2 > 0 then return false end
	
	local tabWTT = {tabWan, tabTiao, tabTong}
	local n1, n2 = 0, 0
	for i = 1, #tabWTT do
		if tabWTT[i].n % 3 == 1 then n1 = n1 + 1 end
		if tabWTT[i].n % 3 == 2 then n2 = n2 + 1 end
	end
	if n1 > nDanTotal then return false end       --单个出现2次以上
	if n2 > nDuiTotal then return false end       --对子个出现3次以上
	if n1 * n2 > 0 then return false end         --单个对子同时出现
	
	if (nZi1 + n1) > nDanTotal then return false end
	if (nZi2 + n2) > nDuiTotal then return false end
	if (nZi1 + n1) * (nZi2 + n2) > 0 then return false end
	return true
end

function MjLogic:ProcessOneColor(tabCur, bCheckHu, tabKsq)    --提取连续的牌并处理
	local wCardIndex = tabCur.w
	if wCardIndex ~= 0 then            --去掉首尾的0
		while (wCardIndex & 1) == 0 do  
			wCardIndex = wCardIndex >> 1
		end
		tabCur.w = wCardIndex
	end
    
    function getN(n)
        local c = 0
        while n > 0 do
          n = n >> 1
          c = c + 1
        end
        return c
    end
    function revN(wCardIndex)
        local c = getN(wCardIndex)
        local r = 0
        while wCardIndex  ~= 0 do    
            if wCardIndex & 1 ~= 0 then r = r + (2 << (c - 2))  end
            c = c - 1
            wCardIndex = wCardIndex >> 1
        end
        return r
    end
    function comps(a,b) return a > b end
    local rWCardIndex = revN(wCardIndex)     --解决123，6不听的bug
    local reverseVal = -1
    if rWCardIndex < wCardIndex then 
      wCardIndex = rWCardIndex
      tabCur.w = rWCardIndex
      table.sort(tabCur.val, comps)
      reverseVal = 1
    end
    
	if tabCur.n == 0 then return 1, {} end
	if tabCur.n == 2 and wCardIndex == 5 then return 0, {tabCur.val[1] + 1} end  --胡卡张
	local tingData = {}
	local nQuan = 1
	local nNotQuan = 0
	local bOk = false
	local indexVal = 0
	local kaZhang = {}
	local wCardIndex2 = wCardIndex
	local paiValTemp = DeepCopy(tabCur.val)
	while wCardIndex2 ~= 0 do    --计算卡张的
		while (wCardIndex2 & 1) == 0 do wCardIndex2 = wCardIndex2 >> 1 end
		if (wCardIndex2 & 7) == 5 then 
			wCardIndex2 = wCardIndex2 - 5
			local k = #tabCur.val - indexVal
			table.insert(paiValTemp, tabCur.val[k] + reverseVal)
			table.sort(paiValTemp)
			if self:ValidPai(paiValTemp) then
				kaZhang[#kaZhang + 1] = tabCur.val[k] + reverseVal
			end
			indexVal = indexVal + 2
			break
		elseif wCardIndex2 & 7 == 7 then
			wCardIndex2 = wCardIndex2 - 7
			indexVal = indexVal + 3
		elseif wCardIndex2 & 3 == 3 then
			wCardIndex2 = wCardIndex2 - 3
			indexVal = indexVal + 2
		else break end		
	end
	if #kaZhang > 1 then return false end
	indexVal = 0
	local n1Or2 = 0    --一个或两个的个数  110011011111
	while wCardIndex ~= 0 do
		local valPai = {}
		while (wCardIndex & 1) == 0 do wCardIndex = wCardIndex >> 1	end
		if (wCardIndex ~= 1) and (wCardIndex & 3) ~= 3 and (wCardIndex & 7) ~= 7 then
			if #kaZhang ~= 1 then  return false                           --11  111或101
			else return 0, kaZhang end
		end 
		local index = {1,2,3,4,5,6,7,8,9,10,11,12,13,14}  --减掉最大的连续数
		for i = #index, 1, -1 do 
			local nIndex = index[i]     --现在去掉了几张
			local v = 2 ^ nIndex - 1  --111,11....
			if (wCardIndex & v == v) then 
				wCardIndex = wCardIndex - v
				indexVal = indexVal + nIndex  --已去掉几张牌
				for j = 1, nIndex do  --去掉的牌组成表,然后判断
					local k = #tabCur.val - indexVal + j
					table.insert(valPai, tabCur.val[k])
				end
				local huPai = {}
				if #valPai <=2 then n1Or2 = n1Or2 + 1 end
				if n1Or2 >= 3 then return false end
				bOk, huPai = self:ProcessSerialPai(valPai, tabKsq)   --333 返回1,{} 23返回0,{1,4}，22 333返回1,{2}(全又不全的返回全1)
				if bOk == 0 then nQuan = 0 nNotQuan = nNotQuan + 1 end
				if nNotQuan > 1 then    --有两个不全的,肯定不听
					tingData = {}
					break
				end 
				if bCheckHu then
					 if bOk ~= 1 then   --检测胡的时候,牌不全直接返回
						if #kaZhang ~= 1 then return false
						else return 0, kaZhang end
					end
				end 
				if not bOk then
					if #kaZhang ~= 1 then return false
					else return 0, kaZhang end
				end
				if tabCur.n % 3 ~= 0 then     --只有不是3的倍数才添加,比如1,1,2,2,3,3,4,6,6 按照这个算法会插入1,4但是整体是9张牌,不应该加牌的!!!
					for i = 1, #huPai do table.insert(tingData, huPai[i]) end
				end
				break
			end
		end
	end
	
	if #kaZhang == 1 then 
		table.insert(tingData, kaZhang[1])
	end
	return nQuan, tingData
end

function MjLogic:ProcessZiPai(tabZi, bCheckHu, tabKsq)
    local nTabZi = #tabZi
    local huPaiData = {}
    for i = 1, nTabZi do 
        local val = self:IndexToVal(27 + i)
        if tabZi[i] == 1 then      
            table.insert(huPaiData, val)
        elseif tabZi[i] == 2 then
            table.insert(huPaiData, val)
            if tabKsq then tabKsq.ksq = TabKsqAdd(tabKsq.ksq, {j = 1, jv = {val}}) end
        elseif tabZi[i] == 3 then
            if tabKsq then tabKsq.ksq = TabKsqAdd(tabKsq.ksq, {k = 1, kv = {val}}) end
        end
    end
    if #huPaiData > 2 then huPaiData = {} return false end
    return true, huPaiData
end

function MjLogic:IsTing(cardIndex, weaveItem, index)
	local numInHand = self:GetHandCardNum(cardIndex)
	if numInHand % 3 ~= 1 then 
		print("In IsTing, HandCardNum Invalid!!! ")
	end
	local tingPaiData = {val = {},type={}}	
	for i = 1, PAICONST.MAX_INDEX do
		tingPaiData[i] = 0
	end
	local bOk, huPaiData = self:GetTingData(cardIndex)	
	if bOk then 
		local cardIndexTemp = DeepCopy(cardIndex)
		for i = 1, #huPaiData do 
			for j = 1, #huPaiData[i] do
				local index = self:ValToIndex(huPaiData[i][j]) 
				cardIndexTemp[index] = cardIndexTemp[index] + 1 
				local huType = HUTYPE.HT_PINGHU
				if self:IsPengPengHu(cardIndexTemp) then huType = HUTYPE.HT_PENGPENGHU end
				local v = huPaiData[i][j]
				local ind = self:ValToIndex(v)
				if tingPaiData[ind] == 0 then 
					tingPaiData[ind] = 1
					tingPaiData.val[#tingPaiData.val + 1] = v
					tingPaiData.type[#tingPaiData.type + 1] = huType
				end
			end
		end
	end

	return tingPaiData
end

function MjLogic:IsHu(cardIndex, weaveItem)
	local numInHand = self:GetHandCardNum(cardIndex)
	if numInHand % 3 ~= 2 then 
		print("In IsHu, HandCardNum Invalid!!! ")
	end
	local tabWan, tabTiao, tabTong, tabZi = self:ParsePaiToWTTZ(cardIndex)
	
	if not self:ValidShouPai(tabWan, tabTiao, tabTong, tabZi) then return false end
	
	local bOkRet = false
	local tabWTTZ = {tabWan, tabTiao, tabTong, tabZi}
	bOkRet = self:ProcessOneColor(tabWTTZ[1])
	if bOkRet ~= 1 then return false end
	bOkRet = self:ProcessOneColor(tabWTTZ[2])
	if bOkRet ~= 1 then return false end
	bOkRet = self:ProcessOneColor(tabWTTZ[3])
	if bOkRet ~= 1 then return false end
	
	local fan = self:GetFanWaiFan(cardIndex, weaveItem)
	return true, fan
end

function MjLogic:ParsePaiToWTTZ(cardIndex)
	local tabWan   = {n = 0, d = 0, w = 0, val = {}}
	local tabTiao  = {n = 0, d = 0, w = 0, val = {}}
	local tabTong  = {n = 0, d = 0, w = 0, val = {}}
	local tabZi    = {0,0,0,0,0,0,0}
	local tabWTTZ = {tabWan, tabTiao, tabTong, tabZi}
	for i = 1, PAICONST.MAX_INDEX do
		local iData = cardIndex[i]
		local v = self:IndexToVal(i)
		local col = (i - 1) // 9 + 1
		if col < 4 then     --万饼条
			for m = 1, iData do table.insert(tabWTTZ[col].val, v) end
			tabWTTZ[col].n = tabWTTZ[col].n + iData
			tabWTTZ[col].d = tabWTTZ[col].d + v * iData
			if tabWTTZ[col].w > 0  then
				tabWTTZ[col].w = tabWTTZ[col].w << math.max(1, iData);      --至少移一位
				tabWTTZ[col].w = tabWTTZ[col].w + ((1 << iData) - 1)
			end
			if iData > 0 and tabWTTZ[col].w == 0 then tabWTTZ[col].w = (1 << iData) - 1	end
		else tabZi[i - 27] = iData end        --字
	end
	return tabWan, tabTiao, tabTong, tabZi
end

function MjLogic:GetFanWaiFan(cardIndex, weaveItem)
	local fan = 0
	--if self:IsPengPengHu(cardIndex) then fan = fan | FAN.PENGPENGHU end
	--if self:IsQingYiSe(cardIndex, weaveItem) then fan = fan | FAN.QINGYISE end
	return fan
end

function MjLogic:GetTingData(cardIndex, weaveItem)    --缺一张牌的情况
	local tabWan, tabTiao, tabTong, tabZi = self:ParsePaiToWTTZ(cardIndex)
	local tabWTT = {tabWan, tabTiao, tabTong}
	
	local bOk = self:ValidShouPai(tabWan, tabTiao, tabTong, tabZi)    --计算听牌时的手牌
	if not bOk then return false end
	
	local huPaiData = {{},{},{},{}}
	local bOk = {false, false, false} 
    
    for i = 1, 3 do
        bOk[i], huPaiData[i] = self:ProcessOneColor(tabWTT[i])    -- 11 56 计算得听{1，4，7}应该去掉1
        if not bOk[i] then return false end
        local huPai = DeepCopy(huPaiData[i]) or {}
        for k, v in pairs(huPai) do
            local pai = DeepCopy(tabWTT[i].val)
            table.insert(pai, v)
            table.sort(pai)
            if not self:ValidPai(pai) then 
                table.remove(huPaiData[i], k)  
            end
        end
        local tTemp = DeepCopy(tabWTT[i])
        if #huPaiData[i] > 0 then tTemp.n = tTemp.n + 1 end
        local tabWTTTemp = DeepCopy(tabWTT)
        tabWTTTemp[i] = tTemp
        if not self:ValidShouPai(tabWTTTemp[1], tabWTTTemp[2], tabWTTTemp[3], tabZi) then return false end
    end
    
    
	-- bOk[1], huPaiData[1] = self:ProcessOneColor(tabWTT[1])
	-- if not bOk[1] then return false end
	-- local tWangTemp = DeepCopy(tabWan)
	-- if #huPaiData[1] > 0 then  tWangTemp.n = tWangTemp.n + 1 end
	-- if not self:ValidShouPai(tWangTemp, tabTiao, tabTong, tabZi) then return false end   --计算胡牌时的手牌,比如前面万有6个是通过的,但是就不能再加一个了
	
	-- bOk[2], huPaiData[2] = self:ProcessOneColor(tabWTT[2])
	-- if not bOk[2] then return false end
	-- local tTiaoTemp = DeepCopy(tabTiao)
	-- if #huPaiData[2] > 0 then tTiaoTemp.n = tTiaoTemp.n + 1 end
	-- if not self:ValidShouPai(tabWan, tTiaoTemp, tabTong, tabZi) then return false end
	
	-- bOk[3], huPaiData[3] = self:ProcessOneColor(tabWTT[3])
	-- if not bOk[3] then return false end
	-- local tTongTemp = DeepCopy(tabTong)
	-- if #huPaiData[3] > 0 then tTongTemp.n = tTongTemp.n + 1 end
	-- if not self:ValidShouPai(tabWan, tabTiao, tTongTemp, tabZi) then return false end
	
	for i = 1, 3 do
		local index1 = (i + 0) % 3 + 1       --取其他的两个,i == 2,其他那就是3,1
		local index2 = (i + 1) % 3 + 1
		if bOk[i] == 0 then huPaiData[index1] = {} huPaiData[index2] = {} end  --{23456，23456789,前者不全时，舍弃后面的听牌，后面的不全时舍弃前面的听牌}
	end
	if (bOk[1] + bOk[2] + bOk[3]) < 3 then   --wtt还差牌,就不要计算字牌了
		return true, huPaiData
	else    --前面已经判断过手牌数量了ValidShouPai
        local bOk, huZi = self:ProcessZiPai(tabZi)
        if bOk then huPaiData[4] = huZi
        else return false end
	end
	
	return true, huPaiData
end

function MjLogic:IsQingYiSe(cardIndex, weaveItem)   --是否为清一色
	local col = 0xFF
	local i = 1
	repeat 
		if cardIndex[i] > 0 then
			if col ~= 0xFF then return false end
			col = self:IndexToVal(i) & PAICONST.MASK_COLOR
			i = (i // 9 + 1) * 9    --跳到下一个色的范围,有就表示不是清一色
		end
		i = i + 1
	until (i > PAICONST.MAX_INDEX)
	if weaveItem ~= nil and #weaveItem > 0 then 
		for i = 1, #weaveItem do 
			if weaveItem[i].CenterCard & PAICONST.MASK_COLOR ~= col then return false end
		end
	end
	return true
end

function MjLogic:IsPengPengHu(cardIndex)
	local double = 0
	for i = 1, #cardIndex do 
		if cardIndex[i] % 3 == 1 then return false end
		if cardIndex[i] % 3 == 2 then double = double + 1 end
		if double > 1 then return false end
	end
	return true
end

